# 1)	数据加载与预处理：
# 加载CIFAR-100数据集，并将其分为训练集和测试集。
import matplotlib.pyplot as plt
from tensorflow.keras.datasets.cifar100 import load_data
from tensorflow.keras import Model,Sequential,optimizers,activations,losses,layers
(x_train,y_train),(x_test,y_test) = load_data()
# 对图像的像素值进行归一化处理，将像素值从[0, 255]缩放到[0, 1]，以改善模型的训练效果。
x_train = x_train / 255
x_test = x_test / 255
# 2)	模型定义定义一个名为AlexNet的自定义模型类。
# 在模型类中，构建了一个卷积神经网络架构，该架构包括五个卷积层（每个卷积层后都有一个最大池化层），用于提取图像中的特征。
# 接着是一个展平层，用于将卷积层输出的多维张量转换为一维数组，以便输入到全连接层中。
# 最后是两个全连接层（每个全连接层后都有一个ReLU激活函数）和一个输出层（具有100个神经元和softmax激活函数），用于对图像进行分类。
class AlexNet(Model):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.conv = Sequential([
            layers.Conv2D(filters=6,kernel_size=(3,3),activation=activations.relu,padding='same'),
            layers.MaxPool2D(),
            layers.Conv2D(filters=16, kernel_size=(3, 3), activation=activations.relu, padding='same'),
            layers.MaxPool2D(),
            layers.Conv2D(filters=24, kernel_size=(3, 3), activation=activations.relu, padding='same'),
            layers.Conv2D(filters=24, kernel_size=(3, 3), activation=activations.relu, padding='same'),
            layers.Conv2D(filters=16, kernel_size=(3, 3), activation=activations.relu, padding='same'),
            layers.MaxPool2D(),
            layers.Flatten()
        ])
        self.fc = Sequential([
            layers.Dense(units=64,activation=activations.relu),
            layers.Dense(units=64,activation=activations.relu),
            layers.Dense(units=100,activation=activations.softmax)
        ])
    def call(self, inputs, training=None, mask=None):
        out = self.conv(inputs)
        out = self.fc(out)
        return out
# 3)	模型编译：
# 使用合适的优化器来编译模型，优化器是一种自适应学习率的方法，能够有效地训练深度神经网络。
# 损失函数设置为稀疏分类交叉熵，因为CIFAR-100的标签是整数形式的。
# 评估指标设置为准确率。
model = AlexNet()
model.compile(optimizer=optimizers.Adam(),loss=losses.sparse_categorical_crossentropy,metrics='acc')
# 4)	模型训练：
# 使用训练集x_train和y_train对模型进行训练，批处理大小为100，训练轮次为10。
model.fit(x_train[:2000],y_train[:2000],batch_size=100,epochs=10)
# 5)	模型评估：
# 使用测试集x_test和y_test对训练好的模型进行评估，计算模型在测试集上的准确率。
model.evaluate(x_test,y_test)
# 6)	权重保存：
# 将训练好的模型的权重保存为HDF5格式的文件（'model.h5'），以便后续使用或进一步分析
model.save_weights('model.h5')
plt.imshow(x_test[0])
plt.show()
